package com.peng.utils;

import cn.hutool.core.util.StrUtil;
import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * GsonUtil
 *
 * @author: zhushiyao
 * @create: 2020/9/2 1:58 下午
 */
public class GsonUtil {

    public static Gson createGson() {
        //设置Gson解析时日期的格式
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
                .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
                .registerTypeAdapter(Integer.class, new IntTypeAdapter())
                .registerTypeAdapter(int.class, new IntTypeAdapter())
                .create();
        return gson;
    }

    public static void main(String[] args) {
        String str = "1.0000000000";
        Double aDouble = Double.parseDouble(str);
        System.out.println(aDouble);
    }

    /**
     * 将bean转换为json
     *
     * @param object
     * @return json串
     * @author zhushiyao
     * @date 2020/9/3 10:15 上午
     */
    public static String toJsonString(Object object) {
        if (object != null) {
            return createGson().toJson(object);
        }
        return null;
    }

    /**
     * 将json转换为jsonObject
     *
     * @param json json串
     * @return json对象
     * @author zhushiyao
     * @date 2020/9/3 10:15 上午
     */
    public static JsonObject parseObject(String json) {
        if (StrUtil.isNotBlank(json)) {
            return createGson().fromJson(json, JsonObject.class);
        }
        return null;
    }

    /**
     * Json转成对象
     *
     * @param gsonString
     * @param clazz
     * @return javaBean
     */
    public static <T> T parseObject(String gsonString, Class<T> clazz) {
        if (gsonString != null) {
            return createGson().fromJson(gsonString, clazz);
        }
        return null;
    }

    /**
     * jsonObject转成java对象
     *
     * @param jsonObject
     * @param clazz
     * @return javaBean
     */
    public static <T> T parseObject(JsonObject jsonObject, Class<T> clazz) {
        if (jsonObject != null && clazz != null) {
            return createGson().fromJson(jsonObject, clazz);
        }
        return null;
    }

    /**
     * json转成List<T>
     *
     * @param gsonString
     * @param clazz
     * @return list<T>
     */
    public static <T> List<T> parseArray(String gsonString, Class<T> clazz) {
        if (gsonString != null) {
            return createGson().fromJson(gsonString, new ParameterizedTypeImpl(clazz));
        }
        return null;
    }

    /**
     * json转成List<T>
     *
     * @param gsonString
     * @return list<T>
     */
    public static JsonArray parseArray(String gsonString) {
        if (gsonString != null) {
            return createGson().fromJson(gsonString, new ParameterizedTypeImpl(JsonArray.class));
        }
        return null;
    }

    /**
     * jsonArray转成List<T>
     *
     * @param jsonArray
     * @param clazz
     * @return list<T>
     */
    public static <T> List<T> parseArray(JsonArray jsonArray, Class<T> clazz) {
        if (jsonArray != null && jsonArray.size() > 0) {
            return createGson().fromJson(jsonArray, new ParameterizedTypeImpl(clazz));
        }
        return null;
    }

    private static class ParameterizedTypeImpl implements ParameterizedType {
        Class clazz;

        public ParameterizedTypeImpl(Class clz) {
            clazz = clz;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return new Type[]{clazz};
        }

        @Override
        public Type getRawType() {
            return List.class;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    }

    /**
     * 处理LocalDate的序列化与反序列化
     */
    final static class LocalDateAdapter implements JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {

        public JsonElement serialize(LocalDate date, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(date.format(DateTimeFormatter.ISO_LOCAL_DATE));
        }

        @Override
        public LocalDate deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
            String timestamp = element.getAsJsonPrimitive().getAsString();
            return LocalDate.parse(timestamp, DateTimeFormatter.ISO_LOCAL_DATE);
        }
    }

    /**
     * 处理LocalDateTime序列化与反序列化
     */
    final static class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime>, JsonDeserializer<LocalDateTime> {

        public JsonElement serialize(LocalDateTime date, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        }

        @Override
        public LocalDateTime deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
            String timestamp = element.getAsJsonPrimitive().getAsString();
            return LocalDateTime.parse(timestamp, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        }
    }

    final static class IntTypeAdapter extends TypeAdapter<Number> {

        @Override
        public void write(JsonWriter out, Number value)
                throws IOException {
            out.value(value);
        }

        @Override
        public Number read(JsonReader in) throws IOException {
            if (in.peek() == JsonToken.NULL) {
                in.nextNull();
                return null;
            }
            String result = in.nextString();
            if ("".equals(result)) {
                return null;
            }
            try {
                return Integer.parseInt(result);
            } catch (NumberFormatException e) {
                return Double.parseDouble(result);
            }
        }
    }
}
